home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-09-18 | 19.5 KB | 908 lines | [TEXT/CWIE] |
- //• ------------------------------------------------------------------------------------------ •
- //•
- //• Copyright © 1996, 1997 Apple Computer, Inc., All Rights Reserved
- //•
- //•
- //• You may incorporate this sample code into your applications without
- //• restriction, though the sample code has been provided "AS IS" and the
- //• responsibility for its operation is 100% yours. However, what you are
- //• not permitted to do is to redistribute the source as "DSC Sample Code"
- //• after having made changes. If you're going to re-distribute the source,
- //• we require that you make it clear in the source that the code was
- //• descended from Apple Sample Code, but that you've made changes.
- //•
- //• Authors:
- //• Jamie Osborne
- //• Chris De Salvo
- //•
- //• ------------------------------------------------------------------------------------------ •
-
- //• ------------------------------ Includes
-
- #include "NetStuff.h"
-
- #include <PLStringFuncs.h>
- #include <stdio.h>
- #include <string.h>
-
- //• ------------------------------ Private Definitions
-
- //• If this is set to 1 then the player enumeration menu item iterates by calling NSpPlayer_GetInfo
- //• rather than using the data in the PlayerEnumeration data structure. This is merely for coverage
- //• testing of the GetInfo call on the client side.
- #define USE_PLAYER_GET_INFO 0
-
- //• ------------------------------ Private Types
-
- enum
- {
- kStandardMessageSize = 1500,
- kBufferSize = 0,
- kQElements = 0,
- kTimeout = 5000,
- kMaxPlayers = 8
- };
-
- //• ------------------------------ Private Variables
-
- static Str31 gameName;
- static Str31 password;
- static Str31 playerName;
- static Str31 kJoinDialogLabel = "\pChoose a Game:";
- static Boolean gInCallback = false;
- static UInt32 gLastUpdate = 0;
- static UInt32 gUpdateFrequency = 2;
- static PlayerInputMessage gPlayerMessage;
- static UInt32 gPlayerMessageSize = 400;
- static GameStateMessage gGameStateMessage;
- static UInt32 gGameStateMessageSize = 1024;
- static UInt32 gSendOptions = kNSpSendFlag_Normal;
- static UInt32 gHostSendOptions = kNSpSendFlag_Registered | kNSpSendFlag_SelfSend;
- static MenuHandle gHostMenuH;
- static UInt32 gHostUpdateFrequency = 2;
- static UInt32 gLastHostUpdate = 0;
- static WindowStuff gWindowStuff[8];
- static NSpPlayerID gMyPlayerID = 0;
-
- //• ------------------------------ Private Functions
-
- static WindowStuff *GetFreeWindowStuff(void);
- static void ReleaseWindowStuff(WindowStuff *inStuff);
- static WindowStuff *GetPlayersWindowStuff(NSpPlayerID inPlayer);
- static WindowPtr FindPlayersWindow(NSpPlayerID inPlayer);
- static void InvalPlayerWindow(NSpPlayerID inPlayer);
- static pascal Boolean MessageHandler(NSpGameReference inGameRef, NSpMessageHeader *inMessage, void *inContext);
- static void InitNetMenu(MenuHandle menu);
- static void GetChooserName(Str255 name);
- static void CloseAllWindows(void);
- static void AddHostMenu(void);
- static void DoAdjustMenu(MenuRef m, UInt32 options, UInt32 updateFrequency, UInt32 messageSize);
- static void DoSendLeaveMessage(NSpPlayerID inID);
- static void DoHandleMessage(NSpMessageHeader *inMessage);
- static void GetMessages(void);
- static void UpdateNetWindows(void);
-
- static void GetInfoEnumeratePlayers(void);
- static void EnumeratePlayers(void);
-
- //• ------------------------------ Public Variables
-
- Boolean gHost = false;
- NSpGameReference gNetGame = nil;
-
- //• -------------------- GetFreeWindowStuff
-
- // this is not reentrant
- static WindowStuff *
- GetFreeWindowStuff(void)
- {
- for (int i = 0; i < 8; i++)
- {
- if (gWindowStuff[i].id == 0)
- return &gWindowStuff[i];
- }
-
- return nil;
- }
-
- //• -------------------- ReleaseWindowStuff
-
- static void
- ReleaseWindowStuff(WindowStuff *inStuff)
- {
- if (inStuff == nil)
- printf("passed in nill stuff pointer!\n");
- else
- memset(inStuff, 0, sizeof(WindowStuff));
- }
-
- //• -------------------- GetPlayersWindowStuff
-
- static WindowStuff *
- GetPlayersWindowStuff(NSpPlayerID inPlayer)
- {
- for (int i = 0; i < 8; i++)
- {
- if (gWindowStuff[i].id == inPlayer)
- return &gWindowStuff[i];
- }
-
- return nil;
-
- }
-
- //• -------------------- FindPlayersWindow
- //•
- //• Finds the window associated with the given player
- static WindowPtr
- FindPlayersWindow(NSpPlayerID inPlayer)
- {
- WindowPtr w;
- WindowStuff *stuff;
- w = FrontWindow();
-
- while (w != nil)
- {
- stuff = (WindowStuff *) GetWRefCon(w);
- if (stuff->id == inPlayer)
- break;
- else
- w = GetNextWindow(w);
- }
-
- return w;
- }
-
- //• -------------------- InvalPlayerWindow
-
- static void
- InvalPlayerWindow(NSpPlayerID inPlayer)
- {
- WindowPtr w = FindPlayersWindow(inPlayer);
-
- if (w)
- {
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(w);
- InvalRect(&w->portRect);
- SetPort(oldPort);
- }
- }
-
-
- //• -------------------- MessageHandler
- //•
- //• this function gets called every time NetSprocket receives a new message.
- //• we use it to prevent our message q from getting too full if we don't idle enough
- //• a good example is when the user has clicked in the menu bar and is reading menus
-
- static pascal Boolean
- MessageHandler(NSpGameReference inGameRef, NSpMessageHeader *inMessage, void *inContext)
- {
- gInCallback = true;
- // if it's a system message, just leave it in the q, so that we can handle it later (when we're
- // not at interrupt time)
- if (inMessage->what & kNSpSystemMessagePrefix)
- return true; // tells NetSprocket to put the message in the message Q
- else // it's one of ours
- {
-
- if (inMessage->what == kPlayerInputMessage && gHost)
- {
- WindowStuff *stuff = GetPlayersWindowStuff(inMessage->from);
- if (stuff)
- {
- stuff->lastMessage = inMessage->id;
- stuff->changed = true;
- }
- return false;
- }
- else if (inMessage->what == kGameStateMessage && !gHost)
- {
- WindowStuff *stuff = GetPlayersWindowStuff(gMyPlayerID);
- if (stuff)
- {
- stuff->lastMessage = inMessage->id;
- stuff->changed = true;
- }
- return false;
- }
- }
- gInCallback = false;
-
- //• If it's some state we haven't considered then better leave it in the queue
- return (true);
- }
-
- //• -------------------- GetChooserName
-
- static void
- GetChooserName(Str255 name)
- {
- StringHandle userName;
-
- userName = GetString(-16096);
- if (userName == nil)
- {
- name[0] = 0;
- }
- else
- {
- PLstrcpy(name, *userName);
- ReleaseResource ((Handle) userName);
- }
- }
-
- //• -------------------- RefreshWindow
-
- void
- RefreshWindow(WindowPtr inWindow)
- {
- WindowStuff *stuff = (WindowStuff *) GetWRefCon(inWindow);
-
- if (stuff->lastMessage != 0)
- NumToString(stuff->lastMessage, stuff->text);
-
- EraseRect(&inWindow->portRect);
-
- MoveTo(20,20);
- DrawString(stuff->text);
- }
-
-
- //• -------------------- InitNetMenu
-
- static void
- InitNetMenu(MenuHandle menu)
- {
- SetItemMark(menu, iJunk, noMark);
- SetItemMark(menu, iNormal, noMark);
- SetItemMark(menu, iRegistered, noMark);
- SetItemMark(menu, iBlocking, noMark);
- SetItemMark(menu, i1X, noMark);
- SetItemMark(menu, i10X, noMark);
- SetItemMark(menu, i30X, noMark);
- SetItemMark(menu, iNoLimit, noMark);
- SetItemMark(menu, iLess500, noMark);
- SetItemMark(menu, i1K, noMark);
- SetItemMark(menu, i10K, noMark);
- SetItemMark(menu, i100K, noMark);
- }
-
- //• -------------------- InitNetworking
-
- OSStatus
- InitNetworking(NSpGameID inGameID)
- {
- OSStatus status;
-
- printf("Initializing NetSprocket... ");
- memset(gWindowStuff, 0, sizeof(WindowStuff) * 8);
- status = NSpInitialize(kStandardMessageSize, kBufferSize, kQElements, inGameID, kTimeout);
- if (status != noErr)
- printf("NSpInitialize returned error %d\n", status);
- else
- printf("Done\n");
-
- // Install an async message handler. We do this so that we won't get hosed if we
- // don't call HandleNetworking often enough (such as a tight loop for mouse-down
- status = NSpInstallAsyncMessageHandler(MessageHandler, nil);
- if (status != noErr)
- printf("NSpInstallAsyncMessageHandler returned error %d\n", status);
-
- MenuHandle h = GetMenuHandle(131);
- if (h)
- InitNetMenu(h);
-
- return status;
- }
-
-
- //• -------------------- CloseAllWindows
-
- static void
- CloseAllWindows(void)
- {
- WindowPtr w, nextWind;
-
- w = FrontWindow();
-
- while (w != nil)
- {
- nextWind = GetNextWindow(w);
- WindowStuff *stuff = (WindowStuff *) GetWRefCon(w);
- if (stuff)
- {
- DisposePtr((Ptr) stuff);
- DisposeWindow(w);
- }
- w = nextWind;
- }
- }
-
-
- //• -------------------- ShutdownNetworking
-
- void
- ShutdownNetworking(void)
- {
- OSStatus status;
-
- if (gNetGame)
- {
- status = NSpGame_Dispose( gNetGame, 0 );
- if (status != noErr)
- {
- printf("NSpGame_Dispose returned error %d\n", status);
- // I REALLY want it to shutdown
- status = NSpGame_Dispose( gNetGame, kNSpGameFlag_ForceTerminateGame );
- if (status != noErr)
- printf("NSpGame_Dispose (force) returned error %d\n", status);
- }
-
- if (gHost)
- {
- DeleteMenu(132);
- ReleaseResource((Handle) gHostMenuH);
- DrawMenuBar();
- }
-
- gNetGame = NULL;
- }
-
- // if there are any windows left, kill them
- CloseAllWindows();
- }
-
-
- //• -------------------- AddHostMenu
-
- static void
- AddHostMenu(void)
- {
- gHostMenuH = GetMenu(132);
- if (gHostMenuH == nil)
- DebugStr("\pCouldn't find menu resource!");
- else
- InsertMenu(gHostMenuH, 0);
-
- InitNetMenu(gHostMenuH);
-
- DrawMenuBar();
- }
-
- //• -------------------- HandleNetMenuChoice
-
- void
- HandleNetMenuChoice(short menu, short item)
- {
- MenuHandle h = GetMenuHandle(menu);
- UInt32 *options;
- UInt32 *frequency;
- UInt32 *size;
-
- if (menu == 132) // host menu
- {
- options = &gHostSendOptions;
- frequency = &gHostUpdateFrequency;
- size = &gGameStateMessageSize;
- }
- else
- {
- options = &gSendOptions;
- frequency = &gUpdateFrequency;
- size = &gPlayerMessageSize;
- }
-
- switch(item)
- {
- case iJunk:
- *options &= 0xFF0FFFFF;
- *options |= kNSpSendFlag_Junk;
- break;
- case iNormal:
- *options &= 0xFF0FFFFF;
- *options |= kNSpSendFlag_Normal;
- break;
- case iRegistered:
- *options &= 0xFF0FFFFF;
- *options |= kNSpSendFlag_Registered;
- break;
- case iBlocking:
- if (*options & kNSpSendFlag_Blocking)
- *options &= ~kNSpSendFlag_Blocking;
- else
- *options |= kNSpSendFlag_Blocking;
- break;
- case i1X:
- *frequency = 60;
- break;
-
- case i10X:
- *frequency = 6;
- break;
-
- case i30X:
- *frequency = 2;
- break;
-
- case iNoLimit:
- *frequency = 0;
- break;
-
- case iLess500:
- *size = 400;
- break;
-
- case i1K:
- *size = 1024;
- break;
-
- case i10K:
- *size = 10240;
- break;
-
- case i100K:
- *size = 102400;
- break;
-
- case iEnumerate:
- #if USE_PLAYER_GET_INFO
- if (131 == menu)
- GetInfoEnumeratePlayers();
- else
- #endif
- EnumeratePlayers();
- break;
-
- default:
- break;
- }
-
- }
-
- //• -------------------- DoAdjustMenu
-
- static void
- DoAdjustMenu(MenuRef m, UInt32 options, UInt32 updateFrequency, UInt32 messageSize)
- {
- if (options & kNSpSendFlag_Junk)
- SetItemMark(m, iJunk, checkMark);
- else
- SetItemMark(m, iJunk, noMark);
-
- if (options & kNSpSendFlag_Normal)
- SetItemMark(m, iNormal, checkMark);
- else
- SetItemMark(m, iNormal, noMark);
-
- if (options & kNSpSendFlag_Registered)
- SetItemMark(m, iRegistered, checkMark);
- else
- SetItemMark(m, iRegistered, noMark);
-
- if (options & kNSpSendFlag_Blocking)
- SetItemMark(m, iBlocking, checkMark);
- else
- SetItemMark(m, iBlocking, noMark);
-
- SetItemMark(m, i1X, noMark);
- SetItemMark(m, i10X, noMark);
- SetItemMark(m, i30X, noMark);
- SetItemMark(m, iNoLimit, noMark);
- switch(updateFrequency)
- {
- case 60:
- SetItemMark(m, i1X, checkMark);
- break;
- case 6:
- SetItemMark(m, i10X, checkMark);
- break;
- case 2:
- SetItemMark(m, i30X, checkMark);
- break;
- default:
- SetItemMark(m, iNoLimit, checkMark);
- break;
- }
-
- SetItemMark(m, iLess500, noMark);
- SetItemMark(m, i1K, noMark);
- SetItemMark(m, i10K, noMark);
- SetItemMark(m, i100K, noMark);
- switch(messageSize)
- {
- case 400:
- SetItemMark(m, iLess500, checkMark);
- break;
- case 1024:
- SetItemMark(m, i1K, checkMark);
- break;
- case 10240:
- SetItemMark(m, i10K, checkMark);
- break;
- case 102400:
- SetItemMark(m, i100K, checkMark);
- break;
- }
-
- }
-
- //• -------------------- AdjustNetMenus
-
- void
- AdjustNetMenus(void)
- {
- MenuRef m = GetMenu(131);
-
- DoAdjustMenu(m, gSendOptions, gUpdateFrequency, gPlayerMessageSize);
-
- if (gHost)
- {
- m = GetMenu(132);
- if (m)
- DoAdjustMenu(m, gHostSendOptions, gHostUpdateFrequency, gGameStateMessageSize);
- }
- }
-
- //• -------------------- DoHost
-
- OSStatus
- DoHost(void)
- {
- OSStatus status;
- Str255 chooserName;
- NSpProtocolListReference theList = NULL;
- Boolean okHit;
-
- // Create an empty protocol list
- status = NSpProtocolList_New(NULL, &theList);
- if (status != noErr)
- {
- printf("NSpProtocolList_New returned error: %d\n", status);
- goto failure;
- }
-
- // Now present a UI for the hosting
- // Note! Do NOT pass in string constants, as the user can change these values
- GetChooserName(chooserName);
- PLstrncpy(playerName, chooserName, 31);
- PLstrcpy(gameName, "\pNetSprocket Test");
- password[0] = 0;
-
- okHit = NSpDoModalHostDialog(theList, gameName, playerName, password, nil);
- if (!okHit)
- {
- status = kUserCancelled;
- goto failure;
- }
-
- // Now host the game
- status = NSpGame_Host(&gNetGame, theList, kMaxPlayers, gameName,
- password, playerName, 0, kNSpClientServer, 0);
- if (status != noErr)
- {
- printf("NSpGame_Host returned error %d\n", status);
- goto failure;
- }
-
- gHost = true;
-
-
- if (status == noErr)
- AddHostMenu();
-
- return status;
-
- failure:
- if (theList != nil)
- NSpProtocolList_Dispose(theList);
-
- return status;
- }
-
- //• -------------------- DoJoin
-
- OSStatus
- DoJoin(void)
- {
- NSpAddressReference theAddress;
- OSStatus status;
- Str255 chooserName;
-
- GetChooserName(chooserName);
- PLstrncpy(playerName, chooserName, 31);
- password[0] = 0;
-
- // Present the UI for joining a game
- // passing an empty string (not nil) for the type causes NetSprocket to use
- // the game id passed in to initialize
- theAddress = NSpDoModalJoinDialog("\p", kJoinDialogLabel, playerName, password, NULL);
- if (theAddress == NULL) // The user cancelled
- return kUserCancelled;
-
-
- status = NSpGame_Join(&gNetGame, theAddress, playerName, password, 0, NULL, 0, 0);
- if (status != noErr)
- printf("NSpGame_Join returned error %d\n", status);
- else
- gHost = false;
-
- return status;
- }
-
- //• -------------------- DoSendLeaveMessage
-
- static void
- DoSendLeaveMessage(NSpPlayerID inID)
- {
- NSpMessageHeader m;
- OSStatus status;
-
- NSpClearMessageHeader(&m);
-
- m.what = kLeaveMessage;
- m.to = inID;
- m.messageLen = sizeof(NSpMessageHeader);
-
- status = NSpMessage_Send(gNetGame, &m, kNSpSendFlag_Registered);
-
- }
-
- //• -------------------- DoCloseNetWindow
-
- void
- DoCloseNetWindow(WindowPtr inWindow)
- {
- if (gHost)
- {
- WindowStuff *stuff = (WindowStuff *) GetWRefCon(inWindow);
- DoSendLeaveMessage(stuff->id);
- }
- else
- ShutdownNetworking();
-
- }
-
- //• -------------------- DoHandleMessage
-
- static void
- DoHandleMessage(NSpMessageHeader *inMessage)
- {
- switch (inMessage->what)
- {
- case kLeaveMessage:
- printf("Got a message telling us to leave the game.");
- ShutdownNetworking();
- break;
- case kNSpPlayerJoined:
- {
- NSpPlayerJoinedMessage *theMessage = (NSpPlayerJoinedMessage *) inMessage;
- printf("Got player joined message: %d\n", theMessage->playerInfo.id);
-
- if (gHost || theMessage->playerInfo.id == NSpPlayer_GetMyID(gNetGame))
- {
- gMyPlayerID = NSpPlayer_GetMyID(gNetGame);
- WindowPtr wind = GetNewCWindow(128, nil, (WindowPtr) -1L);
- if (!wind)
- printf("Failed to create a new window!\n");
- else
- {
- WindowStuff *stuff = GetFreeWindowStuff();
- if (stuff == nil)
- {
- printf("Couldn't alloc memory to show window.\n");
- DisposeWindow(wind);
- }
- else
- {
- stuff->id = theMessage->playerInfo.id;
- stuff->lastMessage = 0;
- PLstrcpy(stuff->text, "\pNew Player");
-
- SetWTitle(wind,theMessage->playerInfo.name);
- SetWRefCon(wind, (long) stuff);
- InvalPlayerWindow(stuff->id);
- }
- }
- }
- }
- break;
-
- case kNSpPlayerLeft:
- {
- char name[32];
-
- NSpPlayerLeftMessage *theMessage = (NSpPlayerLeftMessage *) inMessage;
-
- BlockMoveData(theMessage->playerName + 1, name, theMessage->playerName[0]);
- name[theMessage->playerName[0]] = '\0';
-
- printf("Got player left message: %s, player #%d\n", name, theMessage->playerID);
-
-
- if (gHost)
- {
- WindowPtr w = FindPlayersWindow(theMessage->playerID);
- if (w)
- {
- WindowStuff *stuff = (WindowStuff *) GetWRefCon(w);
- ReleaseWindowStuff(stuff);
- DisposeWindow(w);
- }
- else
- printf("Didn't find the window for the player that left!!\n");
- }
- }
- break;
- case kNSpGameTerminated:
- printf("Got Game terminated message\n");
- ShutdownNetworking();
- break;
-
- default:
- break;
- }
-
- }
-
- //• -------------------- GetMessages
-
- static void
- GetMessages(void)
- {
- NSpMessageHeader *theMessage;
-
- do
- {
- theMessage = NSpMessage_Get(gNetGame);
- DoHandleMessage(theMessage);
- NSpMessage_Release(gNetGame, theMessage);
- } while (gNetGame && theMessage != NULL);
-
- }
-
- //• -------------------- UpdateNetWindows
-
- static void
- UpdateNetWindows(void)
- {
- WindowPtr w;
-
- w = FrontWindow();
-
- while (w != nil)
- {
- WindowStuff *stuff = (WindowStuff *) GetWRefCon(w);
- if (stuff && stuff->changed)
- {
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(w);
- RefreshWindow(w);
- SetPort(oldPort);
-
- stuff->changed = false;
- }
- w = GetNextWindow(w);
- }
- }
-
- //• -------------------- HandleNetwork
-
- void
- HandleNetwork(void)
- {
- OSStatus status;
-
- if (!gNetGame)
- return;
-
- GetMessages();
-
- // update any windows as necessary
- UpdateNetWindows();
-
- UInt32 time = TickCount();
-
- if (gNetGame && time > gLastUpdate + gUpdateFrequency)
- {
- NSpClearMessageHeader(&gPlayerMessage.h);
-
- gPlayerMessage.h.what = kPlayerInputMessage;
- gPlayerMessage.h.to = kNSpHostOnly;
- gPlayerMessage.h.messageLen = gPlayerMessageSize;
-
- // Send my info to the host
- status = NSpMessage_Send(gNetGame, &gPlayerMessage.h, gSendOptions);
- if (status != noErr)
- printf("NSpMessage_Send returned error: %d\n", status);
-
- if (gHost && time > gLastHostUpdate + gHostUpdateFrequency)
- {
- NSpClearMessageHeader(&gGameStateMessage.h);
-
- gGameStateMessage.h.what = kGameStateMessage;
- gGameStateMessage.h.to = kNSpAllPlayers;
- gGameStateMessage.h.messageLen = gGameStateMessageSize;
-
- // Send my info to the host
- status = NSpMessage_Send(gNetGame, &gGameStateMessage.h, gHostSendOptions);
- if (status != noErr)
- printf("NSpMessage_Send returned error: %d\n", status);
-
- gLastHostUpdate = time;
- }
-
- gLastUpdate = time;
- }
- }
-
- //• -------------------- GetInfoEnumeratePlayers
-
- static void
- GetInfoEnumeratePlayers(void)
- {
- OSStatus theErr;
- NSpPlayerEnumerationPtr thePlayers;
- UInt32 i;
-
- if (nil == gNetGame)
- printf("gNetGame is nil.\n");
-
- theErr = NSpPlayer_GetEnumeration(gNetGame, &thePlayers);
- if (noErr != theErr)
- {
- printf("NSpPlayer_GetEnumeration returned %ld\n", theErr);
- return;
- }
-
- printf("PlayerID Name\n");
- printf("-------- -------------------------------\n");
- for (i = 0; i < thePlayers->count; i++)
- {
- char name[sizeof (NSpPlayerName)];
- NSpPlayerInfoPtr thePlayer;
-
- NSpPlayer_GetInfo(gNetGame, thePlayers->playerInfo[i]->id, &thePlayer);
-
- BlockMoveData(thePlayer->name + 1, name, thePlayer->name[0]);
- name[thePlayer->name[0]] = '\0';
- printf("%0.8ld %s\n", thePlayer->id, name);
- }
- }
-
- //• -------------------- EnumeratePlayers
-
- static void
- EnumeratePlayers(void)
- {
- OSStatus theErr;
- NSpPlayerEnumerationPtr thePlayers;
- UInt32 i;
-
- if (nil == gNetGame)
- printf("gNetGame is nil.\n");
-
- theErr = NSpPlayer_GetEnumeration(gNetGame, &thePlayers);
- if (noErr != theErr)
- {
- printf("NSpPlayer_GetEnumeration returned %ld\n", theErr);
- return;
- }
-
- printf("PlayerID Name\n");
- printf("-------- -------------------------------\n");
- for (i = 0; i < thePlayers->count; i++)
- {
- char name[sizeof (NSpPlayerName)];
-
- BlockMoveData(thePlayers->playerInfo[i]->name + 1, name, thePlayers->playerInfo[i]->name[0]);
- name[thePlayers->playerInfo[i]->name[0]] = '\0';
- printf("%0.8ld %s\n", thePlayers->playerInfo[i]->id, name);
- }
- }
-